#pragma once

#include <stdio.h>
#include <share.h>
#include "LinkedList.h"
#include "VMPI_Lock.h"
#ifndef _USE_TIMER_OUTSIDE_
#include "WebkitCOM.h"
#endif

class CLogNode : public CLinkedNode
{
public:
	CLogNode(LPCWSTR v) : logText(v) {}
	~CLogNode() override
	{
		if (logText) HeapFree(GetProcessHeap(), 0, (LPVOID)logText);
	}
	LPCWSTR getLogText() const { return logText; }
protected:
	LPCWSTR logText;
};

class CLogList :public CLinkedList
{
public:
	CLogNode *GetNode() override
	{
		return (CLogNode *)CLinkedList::GetNode();
	}
};

#define debugAdd		add
#define debugAddFlush	addFlush
class LogClass
{
public:
	LogClass(LPCWSTR logfname, bool clearFile = false, bool openFileNow = false);
	~LogClass();
	CString getFileName(){ return CString(fName); }
	void setFileName(LPCWSTR logfname, bool openFileNow);
	__forceinline void setFileName(LPCWSTR logfname){ setFileName(logfname, FileOpened()); }
	__forceinline intptr_t getMaxLength() const { return (intptr_t)maxBufLength; }
protected:
	wchar_t fName[400];
	vmpi_spin_lock lock_flush, lock_buffer;
	CLogList m_logList;
	TICK m_lastCheckTick;
	LPWSTR pBuffer;
	size_t maxBufLength;
	FILE * fLog;

	void _add(LPCWSTR sFormat, va_list pArgList);
public:
	void OpenFile(bool locked);
	void CloseFile(bool locked);
	bool FileOpened() { return fLog != nullptr; }
	__forceinline void addNode(CLogNode *pNode){ if (pNode) m_logList.AddNode(pNode); }
	void addString(LPCWSTR sString);
	void add(LPCWSTR sFormat, ...);
	void addFlush(LPCWSTR sFormat, ...);
	void flush(bool waitIfLocked = false, intptr_t wrNum = -1);
	void checkFlush();
	LPWSTR getBuffer(size_t &bufLength);
	void releaseBuffer();
	LPVOID GetContent(intptr_t &sz);

#ifndef _USE_TIMER_OUTSIDE_
	void addXMLData(intptr_t level, LPCWSTR name, const byte * obj, intptr_t objLen);
	void addIStream(intptr_t level, LPCWSTR name, IStream* obj, LPCWSTR classname = nullptr);
	void addIWebError(intptr_t level, LPCWSTR name, IWebError* obj, LPCWSTR classname = nullptr);
	void addIWebURLRequest(intptr_t level, LPCWSTR name, IWebURLRequest* obj, LPCWSTR classname = nullptr);
	void addIWebURLResponse(intptr_t level, LPCWSTR name, IWebURLResponse* obj, LPCWSTR classname = nullptr);
	void addIWebHTTPURLResponse(intptr_t level, LPCWSTR name, IWebHTTPURLResponse* obj, LPCWSTR classname = nullptr);
	void addIWebMutableURLRequest(intptr_t level, LPCWSTR name, IWebMutableURLRequest* obj, LPCWSTR classname = nullptr);
	void addIWebResource(intptr_t level, LPCWSTR name, IWebResource* obj, LPCWSTR classname = nullptr);
	void addIWebDataSource(intptr_t level, LPCWSTR name, IWebDataSource* obj, LPCWSTR classname = nullptr);
	
	void addIWebView(intptr_t level, LPCWSTR name, IWebView* obj, LPCWSTR classname = nullptr);
	void addIWebFrame(intptr_t level, LPCWSTR name, IWebFrame* obj, LPCWSTR classname = nullptr);
#endif
};

extern LogClass gLog;
extern LogClass gPrc;
